/*
* This file is part of Domodroid.
*
* Domodroid is Copyright (C) 2011 Pierre LAINE, Maxime CHOFARDET
*
* Domodroid is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* Domodroid is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Domodroid. If not, see <http://www.gnu.org/licenses/>.
*
* SPECIAL
* Thank's to http://wptrafficanalyzer.in/blog/android-combined-chart-using-achartengine-library/
*
*/
package widgets;
import android.app.Activity;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Paint.Align;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.github.curioustechizen.ago.RelativeTimeTextView;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.util.MathHelper;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;
import Abstract.calcul;
import Abstract.display_sensor_info;
import Abstract.translate;
import Entity.Entity_Feature;
import Entity.Entity_Map;
import Entity.Entity_client;
import database.WidgetUpdate;
import misc.tracerengine;
import rinor.Rest_com;
import static activities.Activity_Main.SV_Main_ScrollView;
public class Graphical_Info_with_achartengine extends Basic_Graphical_widget implements OnClickListener {
private LinearLayout chartContainer;
private TextView TV_Value;
private RelativeTimeTextView TV_Timestamp;
private int id;
private Message msg;
private static String mytag = "";
public static FrameLayout container = null;
private static FrameLayout myself = null;
private final Boolean with_graph = true;
private Boolean realtime = false;
private GraphicalView mChart;
private String step = "hour";
private int limit = 6; // items returned by Rinor on stats arrays when 'hour' average
private long currentTimestamp = 0;
private long startTimestamp = 0;
private final Date time_start = new Date();
private final Date time_end = new Date();
private int period_type = 0; // 0 = period defined by settings
// 1 = 1 day
// 8 = 1 week
// 30 = 1 month
// 365 = 1 year
private int sav_period;
private float size10;
private float size5;
private XYMultipleSeriesRenderer multiRenderer;
private XYSeriesRenderer incomeRenderer;
private XYSeriesRenderer emptyRenderer;
private XYMultipleSeriesDataset dataset;
private XYSeries nameSeries;
private XYSeries EmptySeries;
private final Entity_Feature feature;
private String state_key;
private String parameters;
private int dev_id;
private final int session_type;
private final SharedPreferences params;
private SimpleDateFormat format;
private TextView state_key_view;
private String stateS;
private String test_unite;
private Float Float_graph_size;
private boolean isopen = false;
public Graphical_Info_with_achartengine(tracerengine Trac,
final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params,
final Entity_Feature feature, Handler handler) {
super(params, activity, Trac, feature.getId(), feature.getDescription(), feature.getState_key(), feature.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler);
this.feature = feature;
this.params = params;
this.session_type = session_type;
onCreate();
}
public Graphical_Info_with_achartengine(tracerengine Trac,
final Activity activity, int widgetSize, int session_type, int place_id, String place_type, SharedPreferences params,
final Entity_Map feature_map, Handler handler) {
super(params, activity, Trac, feature_map.getId(), feature_map.getDescription(), feature_map.getState_key(), feature_map.getIcon_name(), widgetSize, place_id, place_type, mytag, container, handler);
this.feature = feature_map;
this.session_type = session_type;
this.params = params;
onCreate();
}
private void onCreate() {
this.state_key = feature.getState_key();
this.dev_id = feature.getDevId();
this.parameters = feature.getParameters();
this.id = feature.getId();
this.isopen = false;
try {
int graphics_height_size = params.getInt("graphics_height_size", 262);
this.Float_graph_size = Float.valueOf(graphics_height_size);
} catch (Exception e) {
//This is due to old way to store it as a string
String graph_size = params.getString("graph_size", "262.5");
this.Float_graph_size = Float.valueOf(graph_size);
}
format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
mytag = "Graphical_Info_with_achartengine (" + dev_id + ")";
try {
stateS = getResources().getString(translate.do_translate(getContext(), Tracer, state_key));
} catch (Exception e) {
stateS = state_key;
}
myself = this;
setOnClickListener(this);
DisplayMetrics metrics = getResources().getDisplayMetrics();
//Label Text size according to the screen size
float size12 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, metrics);
size10 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, metrics);
size5 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 5, metrics);
float size2 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 2, metrics);
//Design the graph
//Creating a XYMultipleSeriesRenderer to customize the whole chart
multiRenderer = new XYMultipleSeriesRenderer();
//Creating XYSeriesRenderer to customize incomeSeries
incomeRenderer = new XYSeriesRenderer();
emptyRenderer = new XYSeriesRenderer();
//Creating a dataset to hold each series
dataset = new XYMultipleSeriesDataset();
//Creating an XYSeries for Income
nameSeries = new TimeSeries(name);
EmptySeries = new TimeSeries(getResources().getString(translate.do_translate(getContext(), Tracer, "no_value")));
incomeRenderer.setColor(0xff0B909A);
emptyRenderer.setColor(0xffff0000);
incomeRenderer.setPointStyle(PointStyle.CIRCLE);
//emptyRenderer.setPointStyle(PointStyle.CIRCLE);
incomeRenderer.setFillPoints(true);
emptyRenderer.setFillPoints(true);
incomeRenderer.setLineWidth(4);
emptyRenderer.setLineWidth(4);
incomeRenderer.setDisplayChartValues(true);
emptyRenderer.setDisplayChartValues(false);
incomeRenderer.setChartValuesTextSize(size12);
//Change the type of line between point
//incomeRenderer.setStroke(BasicStroke.DASHED);
//Remove default X axis label
//multiRenderer.setXLabels(0);
//Set X title
multiRenderer.setXTitle(getResources().getString(translate.do_translate(getContext(), Tracer, "time")));
//Remove default Y axis label
multiRenderer.setYLabels(0);
//Set X label text color
multiRenderer.setXLabelsColor(Color.BLACK);
//Set Y label text color
multiRenderer.setYLabelsColor(0, Color.BLACK);
//Set X label text size
multiRenderer.setLabelsTextSize(size10);
//Set X label text angle
multiRenderer.setXLabelsAngle(-15);
//Set Y label text angle
multiRenderer.setYLabelsAngle(-10);
//Set X label text alignement
multiRenderer.setXLabelsAlign(Align.CENTER);
//Set to make TV_Value of y axis left aligned
multiRenderer.setYLabelsAlign(Align.LEFT);
//Disable zoom button
multiRenderer.setZoomButtonsVisible(false);
//get background transparent
multiRenderer.setMarginsColor(Color.argb(0x00, 0xff, 0x00, 0x00));
//Disable Zoom in Y axis
multiRenderer.setZoomEnabled(true, false);
//Disable Pan in Y axis
multiRenderer.setPanEnabled(true, false);
//Limits pan mouvement
//[panMinimumX, panMaximumX, panMinimumY, panMaximumY]
//double[] panLimits={-5,26,0,0};
//multiRenderer.setPanLimits(panLimits);
//Sets the selectable radius TV_Value around clickable points.
multiRenderer.setSelectableBuffer(10);
//Add grid
multiRenderer.setShowGrid(true);
//Set color for grid
multiRenderer.setGridColor(Color.BLACK, 0);
//To allow on click method (called when pan or zoom aplied)
multiRenderer.setClickEnabled(true);
Tracer.i(mytag, "New instance for name = " + name + " state_key = " + state_key);
//state key
state_key_view = new TextView(activity);
state_key_view.setText(stateS);
state_key_view.setTextColor(Color.parseColor("#333333"));
//TV_Value
TV_Value = new TextView(activity);
TV_Value.setTextSize(28);
TV_Value.setTextColor(Color.BLACK);
TV_Value.setGravity(Gravity.RIGHT);
Animation animation = new AlphaAnimation(0.0f, 1.0f);
animation.setDuration(1000);
TV_Timestamp = new RelativeTimeTextView(activity, null);
TV_Timestamp.setTextSize(10);
TV_Timestamp.setTextColor(Color.BLUE);
TV_Timestamp.setGravity(Gravity.RIGHT);
super.LL_featurePan.addView(TV_Value);
super.LL_featurePan.addView(TV_Timestamp);
super.LL_infoPan.addView(state_key_view);
test_unite = "";
try {
//Basilic add, number feature has a unit parameter
JSONObject jparam = new JSONObject(parameters.replaceAll(""", "\""));
test_unite = jparam.getString("unit");
} catch (JSONException jsonerror) {
Tracer.i(mytag, "No unit for this feature");
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 9999) {
//Message from widgetupdate
//state_engine send us a signal to notify TV_Value changed
if (session == null)
return;
String new_val = session.getValue();
String Value_timestamp = session.getTimestamp();
Tracer.d(mytag, "Handler receives a new TV_Value <" + new_val + "> at " + Value_timestamp);
Long Value_timestamplong = null;
Value_timestamplong = Long.valueOf(Value_timestamp) * 1000;
display_sensor_info.display(Tracer, new_val, Value_timestamplong, mytag, parameters, TV_Value, TV_Timestamp, activity, LL_featurePan, typefaceweather, typefaceawesome, state_key, state_key_view, stateS, test_unite);
//Change icon if in %
if ((state_key.equalsIgnoreCase("humidity")) || (state_key.equalsIgnoreCase("percent")) || (test_unite.equals("%"))) {
if (Float.parseFloat(new_val) >= 60) {
//To have the icon colored if TV_Value beetwen 30 and 60
change_this_icon(2);
} else if (Float.parseFloat(new_val) >= 30) {
//To have the icon colored if TV_Value >30
change_this_icon(1);
} else {
//To have the icon colored if TV_Value <30
change_this_icon(0);
}
} else {
// #93
if (new_val.equals("off") || new_val.equals("false") || new_val.equals("0") || new_val.equals("0.0")) {
change_this_icon(0);
//set featuremap.state to 1 so it could select the correct icon in entity_map.get_ressources
} else {
change_this_icon(2);
}
}
} else if (msg.what == 9998) {
// state_engine send us a signal to notify it'll die !
Tracer.d(mytag, "state engine disappeared ===> Harakiri !");
session = null;
realtime = false;
removeView(LL_background);
myself.setVisibility(GONE);
if (container != null) {
container.removeView(myself);
container.recomputeViewAttributes(myself);
}
try {
finalize();
} catch (Throwable t) {
t.printStackTrace();
} //kill the handler thread itself
}
}
};
//================================================================================
/*
* New mechanism to be notified by widgetupdate engine when our TV_Value is changed
*
*/
WidgetUpdate cache_engine = WidgetUpdate.getInstance();
if (cache_engine != null)
{
if (api_version <= 0.6f) {
session = new Entity_client(dev_id, state_key, mytag, handler, session_type);
} else if (api_version >= 0.7f) {
session = new Entity_client(id, "", mytag, handler, session_type);
}
try {
if (Tracer.get_engine().subscribe(session)) {
realtime = true; //we're connected to engine
//each time our TV_Value change, the engine will call handler
handler.sendEmptyMessage(9999); //Force to consider current TV_Value in session
}
} catch (Exception e) {
e.printStackTrace();
}
}
//================================================================================
//updateTimer(); //Don't use anymore cyclic refresh....
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
if (visibility == View.VISIBLE) {
}
}
private void compute_period() {
long duration = 0;
//Calendar cal = Calendar.getInstance(); // The 'now' time
switch (period_type) {
case -1:
//user requires the 'Prev' period
period_type = sav_period;
duration = 86400l * 1000l * period_type;
if (time_end != null) {
long new_end = time_end.getTime();
new_end -= duration;
time_end.setTime(new_end);
new_end -= duration;
time_start.setTime(new_end);
}
//Tracer.i(mytag,"type prev on "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end));
break;
case 0:
//user requires the 'Next' period
period_type = sav_period;
duration = 86400l * 1000l * period_type;
if (time_start != null) {
long new_start = time_start.getTime();
new_start += duration;
time_start.setTime(new_start);
new_start += duration;
time_end.setTime(new_start);
}
long new_start = time_start.getTime();
long new_end = time_end.getTime();
long now = System.currentTimeMillis();
if (new_end > now) {
time_end.setTime(now);
double new_timestamp = now - duration;
new_start = (long) new_timestamp;
time_start.setTime(new_start);
}
//Tracer.i(mytag,"type next on "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end));
break;
default:
//period_type indicates the number of days to graph
// relative to 'now' date
duration = 86400l * 1000l * period_type;
long new_end_time = System.currentTimeMillis();
time_end.setTime(new_end_time); //Get actual system time
new_end_time -= duration;
time_start.setTime(new_end_time);
//Tracer.i(mytag,"type = "+period_type+" Begin at :"+sdf.format(time_start)+" End at : "+sdf.format(time_end));
break;
}
if (period_type < 9) {
step = "hour";
limit = 6;
} else if (period_type < 32) {
step = "day";
limit = 5;
} else {
step = "week";
limit = 3;
}
}
private void drawgraph() throws JSONException {
float minf = 0;
float maxf = 0;
float avgf = 0;
//Clear to avoid crash on multiple redraw
EmptySeries.clear();
nameSeries.clear();
dataset.clear();
//Clear all labels
multiRenderer.clearXTextLabels();
multiRenderer.clearYTextLabels();
multiRenderer.removeAllRenderers();
//Set position of graph to 0
//multiRenderer.setXAxisMin(0);
//Set max position of graph to now
//multiRenderer.setXAxisMax(new Date().getTime());
//Adding nameSeries Series to the dataset
dataset.addSeries(nameSeries);
dataset.addSeries(EmptySeries);
//Adding incomeRenderer and emptyRenderer to multipleRenderer
//Note: The order of adding dataseries to dataset and renderers to multipleRenderer
//should be same
multiRenderer.addSeriesRenderer(incomeRenderer);
multiRenderer.addSeriesRenderer(emptyRenderer);
Vector<Vector<Float>> values = new Vector<>();
chartContainer = new LinearLayout(activity);
// Getting a reference to LinearLayout of the MainActivity Layout
chartContainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
chartContainer.setGravity(Gravity.CENTER_VERTICAL);
chartContainer.setPadding((int) size5, (int) size10, (int) size5, (int) size10);
JSONObject json_GraphValues = null;
//todo #131 do this in asynctask
try {
if (api_version <= 0.6f) {
Tracer.i(mytag, "UpdateThread (" + dev_id + ") : " + "stats/" + dev_id + "/" + state_key + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg");
json_GraphValues = Rest_com.connect_jsonobject(activity, Tracer, "stats/" + dev_id +
"/" + state_key +
"/from/" + startTimestamp +
"/to/" + currentTimestamp +
"/interval/" + step +
"/selector/avg", 30000);
} else if (api_version >= 0.7f) {
Tracer.i(mytag, "UpdateThread (" + id + ") : " + "sensorhistory/id/" + id + "/from/" + startTimestamp + "/to/" + currentTimestamp + "/interval/" + step + "/selector/avg");
//Don't forget old "dev_id"+"state_key" is replaced by "id"
json_GraphValues = Rest_com.connect_jsonobject(activity, Tracer, "sensorhistory/id/" + id +
"/from/" + startTimestamp +
"/to/" + currentTimestamp +
"/interval/" + step +
"/selector/avg", 30000);
}
} catch (Exception e) {
//return null;
Tracer.e(mytag, "Error with json");
}
JSONArray itemArray = null;
JSONArray valueArray = new JSONArray();
if (api_version <= 0.6f) {
itemArray = json_GraphValues.getJSONArray("stats");
valueArray = itemArray.getJSONObject(0).getJSONArray("values");
} else if (api_version >= 0.7f) {
try {
valueArray = json_GraphValues.getJSONArray("values");
} catch (Exception e) {
//return null;
Tracer.e(mytag, "Error with json TV_Value");
}
}
int j = 0;
Boolean ruptur = false;
Double real_val;
if (limit == 6) {
// range between 1 to 8 days (average per hour)
for (int i = 0; i < valueArray.length() - 1; i++) {
real_val = valueArray.getJSONArray(i).getDouble(limit - 1);
real_val = calcul.Round_double(real_val);
int year = valueArray.getJSONArray(i).getInt(0);
int month = valueArray.getJSONArray(i).getInt(1);
int week = valueArray.getJSONArray(i).getInt(2);
int day = valueArray.getJSONArray(i).getInt(3);
int hour = valueArray.getJSONArray(i).getInt(4);
int hour_next = valueArray.getJSONArray(i + 1).getInt(4);
//String date=String.valueOf(hour)+"'";
Date date1 = new Date();
try {
date1 = format.parse(String.valueOf(year) + "-"
+ String.valueOf(month) + "-"
+ String.valueOf(day) + " "
+ String.valueOf(hour) + ":00");
Tracer.d(mytag, "date1=" + date1);
Tracer.d(mytag, "Value=" + real_val);
} catch (ParseException e) {
Tracer.d(mytag, "Error converting date");
Tracer.d(mytag, e.toString());
}
if (hour != 23 && (hour < hour_next)) {
//no day change
if ((hour + 1) != hour_next) {
//ruptur : simulate next missing steps
EmptySeries.add(date1.getTime(), real_val);
nameSeries.add(date1.getTime(), real_val);
for (int k = 1; k < (hour_next - hour); k++) {
nameSeries.add(date1.getTime(), MathHelper.NULL_VALUE);
EmptySeries.add(date1.getTime(), real_val);
}
j = j + (hour_next - hour);
ruptur = true;
} else {
if (ruptur) {
EmptySeries.add(date1.getTime(), real_val);
} else {
EmptySeries.add(date1.getTime(), MathHelper.NULL_VALUE);
}
ruptur = false;
nameSeries.add(date1.getTime(), real_val); //change to j to avoid missing TV_Value
j++;
}
} else if (hour == 23) {
if (ruptur) {
EmptySeries.add(date1.getTime(), real_val);
} else {
EmptySeries.add(date1.getTime(), MathHelper.NULL_VALUE);
}
ruptur = false;
nameSeries.add(date1.getTime(), real_val); //change to j to avoid missing TV_Value
j++;
}
if (minf == 0)
minf = real_val.floatValue();
avgf += real_val; // Get the real 'TV_Value'
if (real_val > maxf) {
maxf = real_val.floatValue();
}
if (real_val < minf) {
minf = real_val.floatValue();
}
}
} else if (limit == 5) {
// range between 9 to 32 days (average per day)
for (int i = 0; i < valueArray.length() - 1; i++) {
real_val = valueArray.getJSONArray(i).getDouble(limit - 1);
real_val = calcul.Round_double(real_val);
int year = valueArray.getJSONArray(i).getInt(0);
int month = valueArray.getJSONArray(i).getInt(1);
int day = valueArray.getJSONArray(i).getInt(3);
int day_next = valueArray.getJSONArray(i + 1).getInt(3);
//String date=String.valueOf(hour)+"'";
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.DAY_OF_MONTH, day);
//JAVA calendar month his very strange but start from 0
//find a way to always get the right month this way
month = (month - 1);
//set to 12h because it's an average and much more nice like this.
calendar.set(Calendar.HOUR, 12);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.YEAR, year);
Date date1 = new Date();
date1 = calendar.getTime();
if ((day + 1) != day_next) {
//ruptur : simulate next missing steps
EmptySeries.add(date1.getTime(), real_val);
nameSeries.add(date1.getTime(), real_val);
for (int k = 1; k < (day_next - day); k++) {
nameSeries.add(date1.getTime(), MathHelper.NULL_VALUE);
EmptySeries.add(date1.getTime(), real_val);
}
j = j + (day_next - day);
ruptur = true;
} else {
if (ruptur) {
EmptySeries.add(date1.getTime(), real_val);
Tracer.d(mytag, "date1=" + date1);
Tracer.d(mytag, "Value=" + real_val);
} else {
EmptySeries.add(date1.getTime(), MathHelper.NULL_VALUE);
Tracer.d(mytag, "date1=" + date1);
Tracer.d(mytag, "Value=" + real_val);
}
ruptur = false;
nameSeries.add(date1.getTime(), real_val); //change to j to avoid missing TV_Value
j++;
}
if (minf == 0)
minf = real_val.floatValue();
avgf += real_val; // Get the real 'TV_Value'
if (real_val > maxf) {
maxf = real_val.floatValue();
}
if (real_val < minf) {
minf = real_val.floatValue();
}
}
} else if (limit == 3) {
// (average per week)
for (int i = 0; i < valueArray.length() - 1; i++) {
real_val = valueArray.getJSONArray(i).getDouble(limit - 1);
real_val = calcul.Round_double(real_val);
int year = valueArray.getJSONArray(i).getInt(0);
int week = valueArray.getJSONArray(i).getInt(1);
int week_next = valueArray.getJSONArray(i + 1).getInt(1);
//String date=String.valueOf(hour)+"'";
Calendar calendar = Calendar.getInstance();
calendar.clear();
//set to thursday because it's an average and much more nice like this.
calendar.set(Calendar.DAY_OF_WEEK, 5);
calendar.set(Calendar.WEEK_OF_YEAR, week);
calendar.set(Calendar.YEAR, year);
Date date1 = new Date();
date1 = calendar.getTime();
if (week != 52 && (week < week_next)) {
//no day change
if ((week + 1) != week_next) {
//ruptur : simulate next missing steps
EmptySeries.add(date1.getTime(), real_val);
nameSeries.add(date1.getTime(), real_val);
for (int k = 1; k < (week_next - week); k++) {
nameSeries.add(date1.getTime(), MathHelper.NULL_VALUE);
EmptySeries.add(date1.getTime(), real_val);
}
j = j + (week_next - week);
ruptur = true;
} else {
if (ruptur) {
EmptySeries.add(date1.getTime(), real_val);
Tracer.d(mytag, "date1=" + date1);
Tracer.d(mytag, "Value=" + real_val);
} else {
EmptySeries.add(date1.getTime(), MathHelper.NULL_VALUE);
Tracer.d(mytag, "date1=" + date1);
Tracer.d(mytag, "Value=" + real_val);
}
ruptur = false;
nameSeries.add(date1.getTime(), real_val); //change to j to avoid missing TV_Value
j++;
}
} else if (week == 52) {
if (ruptur) {
EmptySeries.add(date1.getTime(), real_val);
} else {
EmptySeries.add(date1.getTime(), MathHelper.NULL_VALUE);
}
ruptur = false;
nameSeries.add(date1.getTime(), real_val); //change to j to avoid missing TV_Value
j++;
}
if (minf == 0)
minf = real_val.floatValue();
avgf += real_val; // Get the real 'TV_Value'
if (real_val > maxf) {
maxf = real_val.floatValue();
}
if (real_val < minf) {
minf = real_val.floatValue();
}
}
}
avgf = avgf / values.size();
multiRenderer.addYTextLabel(((double) minf) - 1, ("" + minf));
multiRenderer.addYTextLabel(((double) avgf), ("" + avgf));
multiRenderer.addYTextLabel(((double) maxf), ("" + maxf));
//SET limit up and down on Y axis
multiRenderer.setYAxisMin(minf - 1);
multiRenderer.setYAxisMax(maxf + 1);
Tracer.d(mytag, "minf (" + dev_id + ")=" + minf);
Tracer.d(mytag, "maxf (" + dev_id + ")=" + maxf);
Tracer.d(mytag, "avgf (" + dev_id + ")=" + avgf);
Tracer.d(mytag, "UpdateThread (" + dev_id + ") Refreshing graph");
// Specifying chart types to be drawn in the graph
// Number of data series and number of types should be same
// Order of data series and chart type will be same
String types = "dd-MM HH:mm";
// Creating a Timed chart with the chart types specified in types array
mChart = ChartFactory.getTimeChartView(activity, dataset, multiRenderer, types);
mChart.setOnClickListener(new OnClickListener() {
//on click is called when pan or zoom movement id ended
public void onClick(View v) {
Tracer.i(mytag + "Pan or zoom", "New X range=[" + multiRenderer.getXAxisMin() + ", " + multiRenderer.getXAxisMax()
+ "]");
//To get the start of the graph after a move and grab new TV_Value
startTimestamp = ((new Date((long) multiRenderer.getXAxisMin())).getTime()) / 1000;
currentTimestamp = ((new Date((long) multiRenderer.getXAxisMax())).getTime()) / 1000;
Tracer.i(mytag, "Period from " + startTimestamp + " to " + currentTimestamp);
Tracer.i(mytag, "Differcence= " + (currentTimestamp - startTimestamp));
//period_type=1;
long difference = currentTimestamp - startTimestamp;
//Avoid graph to go in the future.
if (currentTimestamp > (System.currentTimeMillis() / 1000)) {
multiRenderer.setXAxisMax(System.currentTimeMillis());
multiRenderer.setXAxisMin(System.currentTimeMillis() - (difference * 1000));
startTimestamp = ((new Date((long) multiRenderer.getXAxisMin())).getTime()) / 1000;
currentTimestamp = ((new Date((long) multiRenderer.getXAxisMax())).getTime()) / 1000;
}
if (difference < 604800) {
period_type = 8;
} else if (difference < 2419200) {
period_type = 31;
} else {
period_type = 33;
}
compute_period();
try {
drawgraph();
} catch (JSONException e) {
e.printStackTrace();
}
mChart.refreshDrawableState();
}
}
);
// Adding the Combined Chart to the LinearLayout
chartContainer.addView(mChart);
}
public void onClick(View arg0) {
if (with_graph) {
//Done correct 350px because it's the source of http://tracker.domogik.org/issues/1804
float size = Float_graph_size * activity.getResources().getDisplayMetrics().density + 0.5f;
int sizeint = (int) size;
if (!isopen) {
this.isopen = true;
try {
LL_background.removeView(chartContainer);
} catch (Exception e) {
e.printStackTrace();
}
try {
period_type = 1; //by default, display 24 hours
compute_period(); //To initialize time_start & time_end
sav_period = period_type; //Save the current graph period
startTimestamp = time_start.getTime() / 1000;
currentTimestamp = time_end.getTime() / 1000;
drawgraph();
} catch (JSONException e) {
Tracer.d(mytag, "Acharengine failed" + e.toString());
}
LL_background.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, sizeint));
LL_background.addView(chartContainer);
this.chartContainer.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
SV_Main_ScrollView.requestDisallowInterceptTouchEvent(true);
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
SV_Main_ScrollView.requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
} else {
this.isopen = false;
LL_background.removeView(chartContainer);
LL_background.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
}
}
}